package com.douqu.game.main.server;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bean.core.util.Utils;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.database.model.UpdateConfigModel;
import com.douqu.game.core.e.E_OffLineType;
import com.douqu.game.core.e.E_ServerTaskType;
import com.douqu.game.core.e.E_UpdateConfigType;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.LoadFactory;
import com.douqu.game.core.factory.PlatformFactory;
import com.douqu.game.core.factory.WordFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.protobuf.SGMainProto;
import com.douqu.game.core.protobuf.SGSystemProto;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.database.mapper.read.ReadUpdateConfigMapper;
import com.douqu.game.main.database.mapper.write.WriteUpdateConfigMapper;
import com.douqu.game.main.server.entity.ServerTask;
import com.douqu.game.main.service.PlayerService;
import com.douqu.game.main.util.CosUtils;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-10-17 18:50
 */
public class UpdateManager {

    private static UpdateManager instance = null;

    private UpdateManager(){}

    public static UpdateManager getInstance()
    {
        if(instance == null)
            instance = new UpdateManager();

        return instance;
    }


    /**
     * 配置文件更新任务
     */
    private List<UpdateConfigModel> configTaskList = new CopyOnWriteArrayList<>();

    /**
     * 服务器维护/开服任务
     */
    private List<ServerTask> serverTaskList = new CopyOnWriteArrayList<>();


    public void load()
    {
        ReadUpdateConfigMapper updateTaskMapper = SpringContext.getBean(ReadUpdateConfigMapper.class);

        configTaskList.clear();
        configTaskList.addAll(updateTaskMapper.findExecuteList());
    }

    public void update(long currentTime)
    {
        for(UpdateConfigModel model : configTaskList)
        {
            if(currentTime >= model.getStartTime().getTime())
            {
                final UpdateConfigModel configModel = model;
                configTaskList.remove(model);
                GameServer.getInstance().startThread(() -> {
                    try{
                        if(!LoadManager.loading)
                        {
                            LogUtils.warn("定时更新开始下载配置文件---->" + configModel.getVersion());
                            if(downloadConfigFile(configModel, PlatformFactory.CONFIG_PATH))
                            {
                                List<String> errorList = testConfig(PlatformFactory.CONFIG_PATH);
                                if(errorList.isEmpty())
                                {
                                    LogUtils.warn("定时更新开始更新配置文件,服务器暂停使用=========================================");

                                    LoadManager.GMLoad();

                                    ServerManager.getInstance().sendLoadData();

                                    GameServer.getInstance().notifyUpdateVersion(configModel.getVersion());

                                    GameServer.getInstance().getWorldManager().dispatchMsg(SGMainProto.E_MSG_ID.MsgID_System_ConfigUpdate_VALUE,
                                            SGSystemProto.S2C_ConfigUpdate.newBuilder().setVersion(configModel.getVersion()).build().toByteArray());

                                    if(configModel.isNotifyActivity())
                                    {
                                        //活动服暂时不支持本地更新
                                        ServerManager.getInstance().sendToActivityUpdateConfig(configModel.getPath(), configModel.getVersion());
                                    }

                                    //配置文件更新完成重新计算
                                    GameServer.getInstance().updateActivity();
//                                    LogUtils.warn("更新活动大厅数据成功 ");
                                }
                                else
                                {
                                    StringBuffer sb = new StringBuffer();
                                    for(String str : errorList)
                                    {
                                        sb.append("\n");
                                        sb.append(str);
                                    }
                                    LogUtils.error("定时更新配置文件" + JSONObject.toJSONString(configModel) + "出错,错误列表如下:" + sb.toString());
                                }
                            }
                            else
                            {
                                LogUtils.error("UpdateConfigTask Error -> downloadFile error!");
                            }
                        }
                        else
                        {
                            LogUtils.error("UpdateConfigTask Error -> loading......");
                        }
                    }catch (Exception e){
                        LogUtils.error("UpdateConfigTask Error -> downloadFile error!");
                        LogUtils.errorException(e);
                    }
                });
            }
        }


        for(ServerTask serverTask : serverTaskList)
        {
            if(serverTask.isTimeout())
            {
                LogUtils.warn("计划任务时间到，开始执行 -> " + serverTask);
                if(serverTask.getType() == E_ServerTaskType.MAINTAIN)
                {
                    GameServer.getInstance().setOpen(false);
                    //TODO 把所有玩家T下线,并提示玩家维护中

                    GameServer.getInstance().startThread(() -> {
                        PlayerService playerService = SpringContext.getBean(PlayerService.class);
                        playerService.saveOnlinePlayer(true);

                        String account = null;
                        for(PlayerController playerController : GameServer.getInstance().getWorldManager().getPlayerList())
                        {
                            account = !Utils.isNullOrEmpty(playerController.getPlayer().getAccount()) ? playerController.getPlayer().getAccount() : playerController.getPlayer().getDeviceId();
                            if(GameServer.getInstance().getWorldManager().isWhite(account))
                                continue;

                            playerController.sendSystem(WordFactory.SERVER_IS_MAINTAIN);

                            ServerManager.getInstance().sendSystem(playerController, WordFactory.getWord(WordFactory.SERVER_IS_MAINTAIN));

                            GameServer.getInstance().getWorldManager().playerExitGame(playerController, E_OffLineType.OFFLINE_SERVER_MAINTAIN);
                        }

                        GameServer.getInstance().notifyServerStatus(SGCommonProto.E_SERVER_STATUS.SERVER_STATUS_CLOSE);
                    });

                }
                else if(serverTask.getType() == E_ServerTaskType.OPEN)
                {
                    GameServer.getInstance().setOpen(true);

                    GameServer.getInstance().notifyServerStatus(SGCommonProto.E_SERVER_STATUS.SERVER_STATUS_FREE);
                }

                serverTaskList.remove(serverTask);
            }
        }
    }

    public boolean downloadConfigFile(UpdateConfigModel configModel, String dataPath) throws Exception
    {
        E_UpdateConfigType type = E_UpdateConfigType.valueOf(configModel.getType());
        if(type == E_UpdateConfigType.REMOTE)
        {
            return CosUtils.downloadFile(configModel.getBucket(), configModel.getPath(), dataPath);
        }
        else if(type == E_UpdateConfigType.LOCAL)
        {
            return CosUtils.copyLocalFile(configModel.getPath(), dataPath);
        }
        else
        {
            return false;
        }
    }

    public List<String> testConfig(String dataPath)
    {
        LoadFactory.setTestLoad(true);

        LoadManager.testLoad(dataPath);

        LoadFactory.setTestLoad(false);

        return DataFactory.getInstance(true).getErrorList();
    }

    public void addConfigTask(UpdateConfigModel model)
    {
        WriteUpdateConfigMapper updateTaskMapper = SpringContext.getBean(WriteUpdateConfigMapper.class);
        updateTaskMapper.create(model);

        configTaskList.add(model);
    }


    public void updateConfigTask(UpdateConfigModel model)
    {
        WriteUpdateConfigMapper updateTaskMapper = SpringContext.getBean(WriteUpdateConfigMapper.class);
        updateTaskMapper.update(model);
    }

    public UpdateConfigModel getConfigTask(UpdateConfigModel model)
    {
        int index = configTaskList.indexOf(model);
        return index >= 0 ? configTaskList.get(0) : configTaskList.get(index);
    }



    public List<UpdateConfigModel> getConfigTaskList()
    {
        return configTaskList;
    }


    public boolean isExistConfigByVersion(String version)
    {
        for(UpdateConfigModel model : configTaskList)
        {
            if(model.getVersion().equals(version))
                return true;
        }
        return false;
    }



    public void addServerTask(ServerTask serverTask)
    {
        if(serverTaskList.contains(serverTask))
            return;

        serverTaskList.add(serverTask);
    }

    public void removeServerTask(int id)
    {
        int index = serverTaskList.indexOf(new ServerTask(id));
        if(index >= 0)
        {
            serverTaskList.remove(index);
        }
    }


    public void initServerTask(JSONArray jsonArray)
    {
        JSONObject jsonObject = null;
        ServerTask serverTask = null;
        for(int i = 0; i < jsonArray.size(); i++)
        {
            jsonObject = jsonArray.getJSONObject(i);
            serverTask = new ServerTask(jsonObject.getInteger("id"));
            serverTask.setStartTime(jsonObject.getLong("startTime"));
            serverTask.setType(E_ServerTaskType.forNumber(jsonObject.getInteger("type")));
            addServerTask(serverTask);
        }
    }

    public List<ServerTask> getServerTaskList()
    {
        return serverTaskList;
    }



}
